package org.leviatan.dataharbour.core.register.control;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;

import org.leviatan.common.xml.XMLIO;
import org.leviatan.dataharbour.core.model.DataEntity;
import org.leviatan.dataharbour.core.model.HarbourRequest;
import org.leviatan.dataharbour.core.model.XmlConvertible;
import org.leviatan.dataharbour.core.model.control.DataEntityHandler;
import org.leviatan.dataharbour.core.model.control.GenericModelXmlHandler;
import org.leviatan.dataharbour.core.model.control.HarbourRequestHandler;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public abstract class RegisterXmlHandler {
	
	
	
	
	///////////////////////////////////////////////////////////////////////////	
	// XML org.w3c.Document generation
	///////////////////////////////////////////////////////////////////////////
	
	
	public static Document createSingleDataModelXmlDoc(XmlConvertible mdl) {
		return XMLIO.getInstance().readXMLString(RegisterXmlHandler.createSingleDataModelXml(mdl));
	}
	
	public static Document createMultipleDataModelsXmlDoc(Collection<XmlConvertible> c) {
		return XMLIO.getInstance().readXMLString(RegisterXmlHandler.createMultipleDataModelsXml(c));
	}
	
	public static Document createMappingsXmlDoc(Map<String, Collection<String>> c) {
		return XMLIO.getInstance().readXMLString(RegisterXmlHandler.createKeyMappingsXml(c));
	}
	
	public static Document createIdListXmlDoc(Collection<String> c) {
		return XMLIO.getInstance().readXMLString(RegisterXmlHandler.createIdListXml(c));
	}
	
	
	
	
	///////////////////////////////////////////////////////////////////////////	
	// XML String generation
	///////////////////////////////////////////////////////////////////////////
	
	public static String createSingleDataModelXml(XmlConvertible mdl) {
		String xml = "";
		xml += "\n\t<model>";
		xml += GenericModelXmlHandler.convertToXml(mdl);
		xml += "\n</model>";
		return xml;
	}
	
	
	public static String createMultipleDataModelsXml(Collection<XmlConvertible> c) {
		String xml = "";
		xml += "\n<data-models>";
		
		XmlConvertible mdl;
		for (Iterator<XmlConvertible> i = c.iterator(); i.hasNext(); ) {
			mdl = i.next();
			xml += RegisterXmlHandler.createSingleDataModelXml(mdl);
		}
		xml += "\n</data-models>";
		return xml;
	}
	
	public static String createKeyMappingsXml(Map<String, Collection<String>> c) {
		String xml = "";
		xml += "\n<mappings>";
		for (Iterator i = c.keySet().iterator(); i.hasNext();) {
			String fromId = i.next().toString();
			xml += "\n\t<mapping>";
			xml += "\n\t\t<from-id><![CDATA[" + fromId + "]]></from-id>";
			
			for (Iterator k = c.values().iterator(); k.hasNext(); ) {
				String toId = k.next().toString();
				xml += "\n\t\t<to-id><![CDATA[" + toId + "]]></to-id>";
			}
			xml += "\n\t</mapping>";
		}
		xml += "\n</mappings>";
		return xml;
	}
	
	public static String createIdListXml(Collection<String> c) {
		String xml = "";
		xml += "\n<list>";
		
		String id;
		for (Iterator<String> i = c.iterator(); i.hasNext(); ) {
			id = i.next();
			xml += "\n\t<id><![CDATA[" + id + "]]></id>";
		}
		xml += "\n</list>";
		return xml;
	}
	
	
	
	
	///////////////////////////////////////////////////////////////////////////
	// Model parsing
	///////////////////////////////////////////////////////////////////////////
	
	public static NodeList getDataModelsNodeList(Document doc) {
		return doc.getElementsByTagName("model");
	}
	
	public static HarbourRequest parseSingleHarbourRequest(Document doc) {
		Element e = (Element) RegisterXmlHandler.getDataModelsNodeList(doc).item(0);
		HarbourRequest hr = HarbourRequestHandler.instantiateModel(e);
		return hr;
	}
	
	public static DataEntity parseSingleDataEntity(Document doc) {
		Element e = (Element) RegisterXmlHandler.getDataModelsNodeList(doc).item(0);
		DataEntity de = DataEntityHandler.instantiateModel(e);
		return de;
	}
	
	
	
	
	///////////////////////////////////////////////////////////////////////////
	// Mapping parsing
	///////////////////////////////////////////////////////////////////////////
	
	
	private static NodeList getMappingsNodeList(Document doc) {
		return doc.getElementsByTagName("mapping");
	}
	
	private static TreeSet<String> instantiateToIdSet(Element e) {
		TreeSet<String> toSet = new TreeSet<String>();
		NodeList list = e.getElementsByTagName("to-id");
		for (int i = 0; i < list.getLength(); i++) {
			Element toElem = (Element) list.item(i);
			String toId = toElem.getTextContent();
			toSet.add(toId);
		}
		return toSet;
	}
	
	private static String getFromId(Element e) {
		return e.getElementsByTagName("from-id").item(0).getTextContent();
	}
	
	public static Hashtable<String, TreeSet<String>> parseMapping(Document doc) {
		NodeList nodeList = RegisterXmlHandler.getMappingsNodeList(doc);
		Hashtable<String, TreeSet<String>> table = new Hashtable<String, TreeSet<String>>();
		for (int i = 0; i < nodeList.getLength(); i++) {
			Element mappingNode = (Element) nodeList.item(i);
			TreeSet<String> toIds = RegisterXmlHandler.instantiateToIdSet(mappingNode);
			String fromId = RegisterXmlHandler.getFromId(mappingNode);
			table.put(fromId, toIds);
		}
		return table;
	}
	
	
	
	
	///////////////////////////////////////////////////////////////////////////
	// Id list parsing
	///////////////////////////////////////////////////////////////////////////
	
	public static TreeSet<String> parseIdList(Document doc) {
		TreeSet<String> idSet = new TreeSet<String>();
		NodeList nodeList = doc.getElementsByTagName("id");
		
		for (int i = 0; i < nodeList.getLength(); i++) {
			String aId = nodeList.item(i).getTextContent();
			idSet.add(aId);
		}
		return idSet;
	}
	
}
	
